# -*- coding: utf-8 -*-
"""
轮动策略框架 | 邢不行 | 2024分享会
author: 邢不行
微信: xbx6660
"""
import os
from Config import *
from Functions import *
from tqdm import tqdm
from joblib import Parallel, delayed
import pandas as pd
import sys
import numpy as np

# 动态读取config里面配置的shift_name脚本
Shift = __import__('shift.%s' % shift_name, fromlist=('',))

# =====取出Shift中配置的变量
# 从Shift中取出 回测持仓周期hold_period
_hold_period = Shift.hold_period
# 从Shift中取出 策略名stg_name
stg_name = Shift.stg_name


def ergodic_back_test(info):
    offset = info[0]
    factor_col = info[1]
    if_ascending = info[2]
    select_num = info[3]
    os.system(f'%s "{root_path}/program/1_轮动策略回测.py" %s %s %s %s %s' % (python_exe, offset, factor_col, if_ascending, select_num, save_path))


if __name__ == '__main__':
    # 设定文件保存的路径
    save_path = os.path.join(root_path, 'data/回测结果/轮动回测结果汇总.csv')
    if os.path.exists(save_path):  # 如果路径存在的话，取出已经跑过回测的参数组合
        exist_data = pd.read_csv(save_path, encoding='gbk')
        exist_data = exist_data.dropna(axis=0).reset_index(drop=True)
        exist_data['选策略因子'] = exist_data['因子'].apply(lambda x: x.split("'")[1] + '_' + x.split(",")[-2].strip())
        exist_data['排序方式'] = exist_data['因子'].apply(lambda x: x.split(',')[1].strip())
        exist_data['排序方式'] = np.where(exist_data['排序方式'] == 'True', True, False)
        exist_data['offset'] = exist_data['offset'].apply(int)
        exist_data['选策略数量'] = exist_data['选策略数量'].apply(int)
        exist_params = exist_data[['offset', '选策略因子', '排序方式', '选策略数量', '策略名', '持仓周期']].values.tolist()
    else:
        exist_params = []

    # 设定想遍历的因子
    ratation_factors = get_file_in_folder(root_path + '/program/factors/', file_type='.py', filters=['__init__'], drop_type=True)
    #ratation_factors = ['Bias']  # 可以配置多个因子，但是实际选策略只支持单因子

    # 设定想遍历的因子参数
    factor_param_list = [30,60,80,100,120,140,160,180,200,220,260,300,350]

    # 设定想遍历的因子排序方式
    if_ascendings = [False]

    # 设定想遍历的offset，默认全offset(持仓周期为config中指定策略的持仓周期)
    offsets = list(range(0, int(_hold_period[:-1])))

    # 设定想遍历的选策略数量
    select_nums = [1]

    factor_cols = []
    for factor in ratation_factors:
        for params in factor_param_list:
            factor_col = factor + '_' + str(params)
            factor_cols.append(factor_col)

    infos = []
    for factor_col in factor_cols:
        for if_ascending in if_ascendings:
            for offset in offsets:
                for select_num in select_nums:
                    info = [offset, factor_col, if_ascending, select_num, stg_name, _hold_period]
                    if info not in exist_params:
                        infos.append(info)

    python_exe = sys.executable
    # 多线程执行还是单线程执行
    multiple_process = True
    if multiple_process:
        Parallel(n_jobs=n_jobs)(delayed(ergodic_back_test)(item) for item in tqdm(infos))
    else:
        for item in tqdm(infos[:2]):
            ergodic_back_test(item)
